/**
 * 
 */
package edu.pw.treegrid.server.query;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import edu.pw.treegrid.server.classmodel.DomainClass;
import edu.pw.treegrid.server.filter.AndFilter;
import edu.pw.treegrid.server.filter.IdFilter;
import edu.pw.treegrid.server.filter.Filter;
import edu.pw.treegrid.server.message.Hierarchy;
import edu.pw.treegrid.server.message.Path;
import edu.pw.treegrid.server.reportmodel.Report;
import edu.pw.treegrid.server.reportmodel.ReportColumn;


/** 
 * @author Piotrek
 */
public class QueryGenerator {
	/** 
	 * @param report
	 * @param hierarchy
	 * @param filter
	 * @param path
	 * @return
	 */
	public QueryTree generateQueryTree(Report report, Hierarchy hierarchy,
			Filter filter, Path path) {
		QueryTree queryTree = new QueryTree();
		queryTree.setGroupByColumns(getGroupByColumn(hierarchy, path));
		TableNode tableNode = new TableNode();
		DomainClass mainClass = report.getMainClass();
		if(mainClass.getPrimaryAttribute() == null){
			System.out.println("Primary attribute has not been set properly.");
		}
		tableNode.setPrimaryKeyName(mainClass.getPrimaryAttribute()
				.getExpression());
		tableNode.setTableName(mainClass.getTableName());
		tableNode.setNumber(1);
		queryTree.setRootTable(tableNode);
		for (ReportColumn rc : report.getColumns()) {
			queryTree.mergeWith(rc);
		}
		Filter hierarchyFilter = buildFilter(hierarchy, path);
		
		List<Filter> filters = new LinkedList<Filter>();
		if(hierarchyFilter != null) {
			filters.add(hierarchyFilter);
		}
		if(filter != null) {
			filters.add(filter);
		}
		if(report.getFilter() != null) {
			filters.add(report.getFilter());
		}
		
		if(filters.size() == 1) {
			queryTree.setFilter(filters.get(0));
		}
		else if(filters.size() > 1) {
			AndFilter andFilter = new AndFilter();
			for(Filter f : filters) {
				andFilter.addFilter(f);
			}
			queryTree.setFilter(andFilter);
		}

		return queryTree;
	}

	/** 
	 * @param hierarchy
	 * @param path
	 */
	private Filter buildFilter(Hierarchy hierarchy, Path path) {
		AndFilter andFilter = new AndFilter();
		Iterator<Object> valueIterator = path.getPath().iterator();
		Iterator<ReportColumn> columnIterator = hierarchy.getGroupColumns()
				.iterator();
		valueIterator.next(); // pierwsza wartosc to null
		if(!valueIterator.hasNext()) {
			return null;
		}
		while (valueIterator.hasNext()) {
			IdFilter filter = new IdFilter();
			filter.setReportColumn(columnIterator.next());
			filter.setValue(valueIterator.next());
			andFilter.addFilter(filter);
		}
		return andFilter;
	}

	private List<ReportColumn> getGroupByColumn(Hierarchy hierarchy, Path path) {
		List<ReportColumn> result = new LinkedList<ReportColumn>();
		int pathSize = path.getPath().size() - 1;

		if (pathSize != hierarchy.getGroupColumns().size()) {
			for (ReportColumn rc : hierarchy.getGroupColumns()) {
				if (pathSize == 0) {
					result.add(rc);
					break;
				}
				pathSize--;
			}
		}

		return result;
	}
}